package ma.model.auxillary;

import java.util.ArrayList;
import java.util.Collection;

import ma.model.Observable;
import ma.view.gui.ObserverInterface;

/**
 * The Parameter class defines a parameter which allows to compute the minimum
 * energy consumption of a manufacturing process. It contains a name, an
 * abbreviation, a unit and a category. Categories like machine parameters,
 * material parameters, geometry parameters etc. 
 * @author Oliver Eckstein
 *
 */
public class Parameter implements Observable, Comparable<Parameter> {
    private final String NAME;
    private final String ABBREVIATION;
    private final String GUI_ABBREVIATION;
    private final String UNIT;
    private final int ORDER;
    private final String KEY;
    private boolean dependence;
    private Double value = null;
    private Collection<ObserverInterface> observers =
            new ArrayList<ObserverInterface>();
    
    /**
     * The Type enum holds a parameter's category.
     * @author Oliver Eckstein
     *
     */
    public enum Type
    {
        MATERIAL_PARAMETER,
        PROCESS_PARAMETER,
        GEOMETRY_PARAMETER,
        DEPENDENT_PARAMETER,
        TOOL_PARAMETER
    }
    
    /**
     * To create a new instance of a {@code Parameter}.
     * @param name name of parameter.
     * @param abbreviation abbreviation of parameter.
     * @param guiAbbreviation abbreviation for GUI purposes.
     * @param unit unit of parameter.     
     * @param order order of parameter if stored in a list.
     * @param key identifying key of the parameter.
     * @param dependence <br>{@code true} parameter depends on calculations.
     * <br>{@code false} parameter is set by the user.
     * @param value value of parameter.
     */
    public Parameter(
           String name,
           String abbreviation,
           String guiAbbreviation,
           String unit,           
           int order,
           String key,
           boolean dependence,
           Double value
           )
    {
        NAME = name;        
        ABBREVIATION = abbreviation;
        GUI_ABBREVIATION = guiAbbreviation;
        UNIT = unit;        
        ORDER = order;
        KEY = key;
        this.dependence = dependence;
        if (value == null) {
            this.value = Double.NaN;
        } else {
            this.value = value;    
        }        
    }
    
    /**
     * To create a new instance of a {@code Parameter}. It's value is set to
     * {@code Double.NaN}.
     * @param name name of parameter.
     * @param abbreviation abbreviation of parameter.
     * @param guiAbbreviation abbreviation for GUI purposes.
     * @param unit unit of parameter.     
     * @param order order of parameter if stored in a list.
     * @param key identifying key of the parameter.
     * @param dependence <br>{@code true} parameter depends on calculations.
     * <br>{@code false} parameter is set by the user.     
     */
    public Parameter(
           String name,
           String abbreviation,
           String guiAbbreviation,
           String unit,           
           int order,
           String key,
           boolean dependence           
           )
    {
        NAME = name;        
        ABBREVIATION = abbreviation;
        GUI_ABBREVIATION = guiAbbreviation;
        UNIT = unit;        
        ORDER = order;
        KEY = key;
        this.dependence = dependence;
        value = Double.NaN;        
    }
    
    /**
     * To get the parameter's name.
     * @return the parameter's name.
     */
    public String getName() {
        return NAME;
    }
    
    /**
     * To get the parameter's abbreviation.
     * @return the parameter's abbreviation.
     */
    public String getAbbreviation() {
        return ABBREVIATION;
    }
    
    /**
     * To get the parameter's GUI abbreviation.
     * @return the parameter's GUI abbreviation.
     */
    public String getGuiAbbreviation()
    {
        return GUI_ABBREVIATION;
    }
    
    /**
     * To get the parameter's unit.
     * @return the parameter's unit.
     */
    public String getUnit() {
        return UNIT;
    }
    
    /**
     * To get the parameter's dependence.
     * @return the parameter's dependence.
     */
    public boolean getDependence()
    {
        return dependence;
    }
    
    /**
     * To get the parameter's order number.
     * @return the parameter's order number.
     */
    public int getOrder()
    {
        return ORDER;
    }
    
    /**
     * To get the parameter's value.
     * @return the parameter's value.
     */
    public Double getValue() {
        return value;
    }
    
    public String getKey()	 {
    	return KEY;
    }
    
    /**
     * To set the parameter's value.
     * @param value value to be set.
     * @throws IllegalArgumentException
     */
    public void setValue(Double value) throws IllegalArgumentException {
        if (value == null)
            throw new IllegalArgumentException(
                    "Value of parameter must be set!");
        this.value = value;
    }
    
    /**
     * To set the parameter's dependence.
     * @param dependence the parameter's dependence.
     */
    public void setDependence(boolean dependence)
    {
        this.dependence = dependence;
    }
    
    @Override
    /*
     * (non-Javadoc)
     * @see ma.model.Observable#registerObserver(ma.view.gui.ObserverInterface)
     */
    public void registerObserver(ObserverInterface observer)
    {
        observers.add(observer);        
    }
    
    @Override
    /* (non-Javadoc)
     * @see ma.model.Observable#deleteObserver(ma.model.Observable)
     */
    public void removeObserver(ObserverInterface observer)
    {
        if(observers.contains(observer))
        {
            observers.remove(observer);            
        }
    }
    
    @Override
    /* (non-Javadoc)
     * @see ma.model.Observable#notifyObservers(ma.model.Observable)
     */
    public void notifyObservers()
    {        
        for(ObserverInterface observer : observers)
        {
            observer.update();                 
        }        
    }

    @Override
    public int compareTo(Parameter that) {
        return Integer.compare(this.ORDER, that.ORDER);
    }
    
    @Override
    public String toString() {
        return ("Parameter '" + ABBREVIATION + "'");
    }
    
    /**
     * To indicate whether this parameter was set by a user or not.
     * @return true when parameter was set by a user.
     */
    public boolean isSet() {
        if (Double.isNaN(value)) {
            return false;
        } else {
            return true;
        }
    }
}
